package cn.jw.starter.web.core.interceptors;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.Ordered;
import org.springframework.util.StreamUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.util.ContentCachingResponseWrapper;
import org.springframework.web.util.WebUtils;

import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

/**
 * 请求日志记录
 *
 * @author wgslucky
 * @since 2024/4/30 1:19
 **/
public class RequestLogInterceptor implements HandlerInterceptor, Ordered {
    private Logger logger = LoggerFactory.getLogger(RequestLogInterceptor.class);

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE - 100;
    }

    private boolean isNeedLog(HttpServletRequest request) {
        String contentType = request.getContentType();
        if (contentType == null) {
            return false;
        }
        if (contentType.contains("application/json")) {
            return true;
        }
        return false;
    }

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        throws Exception {
        if (!this.isNeedLog(request)) {
            return true;
        }
        String requestUri = request.getRequestURI();

        String body = StreamUtils.copyToString(request.getInputStream(), StandardCharsets.UTF_8);
        if (StringUtils.isEmpty(body)) {
            body = "无请求参数";
        }
        logger.info("client request ({})-> {}", requestUri, body);
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
        throws Exception {
        if (!this.isNeedLog(request)) {
            return;
        }
        String requestUri = request.getRequestURI();
        if (logger.isInfoEnabled()) {
            ContentCachingResponseWrapper wrapper =
                WebUtils.getNativeResponse(response, ContentCachingResponseWrapper.class);
            if (wrapper != null) {
                String responseBody =
                    IOUtils.toString(wrapper.getContentAsByteArray(), StandardCharsets.UTF_8.toString());
                logger.info("server response ({}) <-- {}", requestUri, responseBody);
            }
        }
        this.updateResponse(response);
    }

    /**
     * 更新响应（不操作这一步，会导致接口响应空白）
     *
     * @param response
     *            响应对象
     * @throws IOException
     *             /
     */
    private void updateResponse(HttpServletResponse response) throws IOException {
        ContentCachingResponseWrapper responseWrapper =
            WebUtils.getNativeResponse(response, ContentCachingResponseWrapper.class);
        if (responseWrapper == null) {
            logger.warn("响应类型: {}", response.getClass().getName());
        } else {
            Objects.requireNonNull(responseWrapper).copyBodyToResponse();
        }
    }
}
